home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / shells / bashsrc.zoo / readline / history.c < prev    next >
C/C++ Source or Header  |  1991-05-29  |  35KB  |  1,479 lines

  1. /* History.c -- standalone history library */
  2.  
  3. /* Copyright (C) 1989 Free Software Foundation, Inc.
  4.  
  5.    This file contains the GNU History Library (the Library), a set of
  6.    routines for managing the text of previously typed lines.
  7.  
  8.    The Library is free software; you can redistribute it and/or modify
  9.    it under the terms of the GNU General Public License as published by
  10.    the Free Software Foundation; either version 1, or (at your option)
  11.    any later version.
  12.  
  13.    The Library is distributed in the hope that it will be useful, but
  14.    WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.    General Public License for more details.
  17.  
  18.    The GNU General Public License is often shipped with GNU software, and
  19.    is generally kept in a file called COPYING or LICENSE.  If you do not
  20.    have a copy of the license, write to the Free Software Foundation,
  21.    675 Mass Ave, Cambridge, MA 02139, USA. */
  22.  
  23. /* The goal is to make the implementation transparent, so that you
  24.    don't have to know what data types are used, just what functions
  25.    you can call.  I think I have done that. */
  26.  
  27. /* Remove these declarations when we have a complete libgnu.a. */
  28. #define STATIC_MALLOC
  29. #ifndef STATIC_MALLOC
  30. extern char *xmalloc (), *xrealloc ();
  31. #else
  32. static char *xmalloc (), *xrealloc ();
  33. #endif
  34.  
  35. #include <stdio.h>
  36.  
  37. #ifdef __GNUC__
  38. #define alloca __builtin_alloca
  39. #else
  40. #if defined (sparc) && defined (sun)
  41. #include <alloca.h>
  42. #else
  43. extern char *alloca ();
  44. #endif
  45. #endif
  46.  
  47. #include "history.h"
  48.  
  49. #ifndef savestring
  50. #define savestring(x) (char *)strcpy (xmalloc (1 + strlen (x)), (x))
  51. #endif
  52.  
  53. #ifndef whitespace
  54. #define whitespace(c) (((c) == ' ') || ((c) == '\t'))
  55. #endif
  56.  
  57. #ifndef digit
  58. #define digit(c)  ((c) >= '0' && (c) <= '9')
  59. #endif
  60.  
  61. #ifndef member
  62. #define member(c, s) ((c) ? index ((s), (c)) : 0)
  63. #endif
  64.  
  65. /* **************************************************************** */
  66. /*                                    */
  67. /*            History functions                */
  68. /*                                    */
  69. /* **************************************************************** */
  70.  
  71. /* An array of HIST_ENTRY.  This is where we store the history. */
  72. static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
  73.  
  74. /* Non-zero means that we have enforced a limit on the amount of
  75.    history that we save. */
  76. static int history_stifled = 0;
  77.  
  78. /* If HISTORY_STIFLED is non-zero, then this is the maximum number of
  79.    entries to remember. */
  80. static int max_input_history;
  81.  
  82. /* The current location of the interactive history pointer.  Just makes
  83.    life easier for outside callers. */
  84. static int history_offset = 0;
  85.  
  86. /* The number of strings currently stored in the input_history list. */
  87. static int history_length = 0;
  88.  
  89. /* The current number of slots allocated to the input_history. */
  90. static int history_size = 0;
  91.  
  92. /* The number of slots to increase the_history by. */
  93. #define DEFAULT_HISTORY_GROW_SIZE 50
  94.  
  95. /* The character that represents the start of a history expansion
  96.    request.  This is usually `!'. */
  97. char history_expansion_char = '!';
  98.  
  99. /* The character that invokes word substitution if found at the start of
  100.    a line.  This is usually `^'. */
  101. char history_subst_char = '^';
  102.  
  103. /* During tokenization, if this character is seen as the first character
  104.    of a word, then it, and all subsequent characters upto a newline are
  105.    ignored.  For a Bourne shell, this should be '#'.  Bash special cases
  106.    the interactive comment character to not be a comment delimiter. */
  107. char history_comment_char = '\0';
  108.  
  109. /* The list of characters which inhibit the expansion of text if found
  110.    immediately following history_expansion_char. */
  111. char *history_no_expand_chars = " \t\n\r=";
  112.  
  113. /* The logical `base' of the history array.  It defaults to 1. */
  114. int history_base = 1;
  115.  
  116. /* Begin a session in which the history functions might be used.  This
  117.    initializes interactive variables. */
  118. void
  119. using_history ()
  120. {
  121.   history_offset = history_length;
  122. }
  123.  
  124. /* Place STRING at the end of the history list.  The data field
  125.    is  set to NULL. */
  126. void
  127. add_history (string)
  128.      char *string;
  129. {
  130.   HIST_ENTRY *temp;
  131.  
  132.   if (history_stifled && (history_length == max_input_history)) {
  133.     register int i;
  134.  
  135.     /* If the history is stifled, and history_length is zero,
  136.        and it equals max_input_history, we don't save items. */
  137.     if (!history_length)
  138.       return;
  139.  
  140.     /* If there is something in the slot, then remove it. */
  141.     if (the_history[0]) {
  142.       free (the_history[0]->line);
  143.       free (the_history[0]);
  144.     }
  145.  
  146.     for (i = 0; i < history_length; i++)
  147.       the_history[i] = the_history[i + 1];
  148.  
  149.     history_base++;
  150.  
  151.   } else {
  152.  
  153.     if (!history_size) {
  154.       the_history =
  155.     (HIST_ENTRY **)xmalloc ((history_size = DEFAULT_HISTORY_GROW_SIZE)
  156.               * sizeof (HIST_ENTRY *));
  157.       history_length = 1;
  158.  
  159.     } else {
  160.       if (history_length == (history_size - 1)) {
  161.     the_history =
  162.       (HIST_ENTRY **)xrealloc (the_history,
  163.                    ((history_size += DEFAULT_HISTORY_GROW_SIZE)
  164.                     * sizeof (HIST_ENTRY *)));
  165.       }
  166.       history_length++;
  167.     }
  168.   }
  169.  
  170.   temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
  171.   temp->line = savestring (string);
  172.   temp->data = (char *)NULL;
  173.  
  174.   the_history[history_length] = (HIST_ENTRY *)NULL;
  175.   the_history[history_length - 1] = temp;
  176. }
  177.  
  178. /* Make the history entry at WHICH have LINE and DATA.  This returns
  179.    the old entry so you can dispose of the data.  In the case of an
  180.    invalid WHICH, a NULL pointer is returned. */
  181. HIST_ENTRY *
  182. replace_history_entry (which, line, data)
  183.      int which;
  184.      char *line;
  185.      char *data;
  186. {
  187.   HIST_ENTRY *temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
  188.   HIST_ENTRY *old_value;
  189.  
  190.   if (which >= history_length)
  191.     return ((HIST_ENTRY *)NULL);
  192.  
  193.   old_value = the_history[which];
  194.  
  195.   temp->line = savestring (line);
  196.   temp->data = data;
  197.   the_history[which] = temp;
  198.  
  199.   return (old_value);
  200. }
  201.  
  202. /* Returns the magic number which says what history element we are
  203.    looking at now.  In this implementation, it returns history_offset. */
  204. int
  205. where_history ()
  206. {
  207.   return (history_offset);
  208. }
  209.  
  210. /* Search the history for STRING, starting at history_offset.
  211.    If DIRECTION < 0, then the search is through previous entries,
  212.    else through subsequent.  If the string is found, then
  213.    current_history () is the history entry, and the value of this function
  214.    is the offset in the line of that history entry that the string was
  215.    found in.  Otherwise, nothing is changed, and a -1 is returned. */
  216. int
  217. history_search (string, direction)
  218.      char *string;
  219.      int direction;
  220. {
  221.   register int i = history_offset;
  222.   register int reverse = (direction < 0);
  223.   register char *line;
  224.   register int index;
  225.   int string_len = strlen (string);
  226.  
  227.   /* Take care of trivial cases first. */
  228.  
  229.   if (!history_length || (i == history_length) && !reverse)
  230.     return (-1);
  231.  
  232.   if (reverse && (i == history_length))
  233.     i--;
  234.  
  235.   while (1)
  236.     {
  237.       /* Search each line in the history list for STRING. */
  238.  
  239.       /* At limit for direction? */
  240.       if ((reverse && i < 0) ||
  241.       (!reverse && i == history_length))
  242.     return (-1);
  243.  
  244.       line = the_history[i]->line;
  245.       index = strlen (line);
  246.  
  247.       /* If STRING is longer than line, no match. */
  248.       if (string_len > index)
  249.     goto next_line;
  250.  
  251.       /* Do the actual search. */
  252.       if (reverse)
  253.     {
  254.       index -= string_len;
  255.  
  256.       while (index >= 0)
  257.         {
  258.           if (strncmp (string, line + index, string_len) == 0)
  259.         {
  260.           history_offset = i;
  261.           return (index);
  262.         }
  263.           index--;
  264.         }
  265.     }
  266.       else
  267.     {
  268.       register int limit = (string_len - index) + 1;
  269.       index = 0;
  270.  
  271.       while (index < limit)
  272.         {
  273.           if (strncmp (string, line + index, string_len) == 0)
  274.         {
  275.           history_offset = i;
  276.           return (index);
  277.         }
  278.           index++;
  279.         }
  280.     }
  281.     next_line:
  282.       if (reverse)
  283.     i--;
  284.       else
  285.     i++;
  286.     }
  287. }
  288.  
  289. /* Remove history element WHICH from the history.  The removed
  290.    element is returned to you so you can free the line, data,
  291.    and containing structure. */
  292. HIST_ENTRY *
  293. remove_history (which)
  294.      int which;
  295. {
  296.   HIST_ENTRY *return_value;
  297.  
  298.   if (which >= history_length || !history_length)
  299.     return_value = (HIST_ENTRY *)NULL;
  300.   else
  301.     {
  302.       register int i;
  303.       return_value = the_history[which];